﻿/*****************************************
 * 
 *  copyright (c) by ylshen
 * 
 *  author : ylshen (syl.lucky@gmail.com)
 *  
 **************************************** */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace JYStockAnalyser.Model
{
    /// <summary>
    /// 财务计算器
    /// </summary>
    public class FinancialCalculator
    {
        /// <summary>
        /// 计算增长率
        /// </summary>
        /// <param name="beginValue">始值</param>
        /// <param name="endValue">终值</param>
        /// <returns></returns>
        public static decimal CalculateGrowthRate(decimal beginValue, decimal endValue)
        {
            if (beginValue <= 0) return GuideLine.UNDEFINED_VALUE;

            return decimal.Round((decimal)((endValue - beginValue) / beginValue), 4);
        }

        /// <summary>
        /// 获取增长率字符串
        /// </summary>
        /// <param name="beginValue">始值</param>
        /// <param name="endValue">终值</param>
        /// <returns></returns>
        public static string GetGrowthRateString(decimal beginValue, decimal endValue)
        {
            decimal v = CalculateGrowthRate(beginValue, endValue);

            return GetPercentString(v);
        }

        public static string GetPercentString(decimal v)
        {
            return v.Equals(GuideLine.UNDEFINED_VALUE) ? "-" : (v * 100).ToString("0.00") + "%";
        }

        /// <summary>
        /// 计算复合增长率
        /// </summary>
        /// <param name="beignValue">始值</param>
        /// <param name="endValue">终值</param>
        /// <param name="period">期数</param>
        /// <returns></returns>
        public static decimal CalculateCompoundGrowthRate(decimal beignValue, decimal endValue, int period)
        {
            if (endValue.Equals(GuideLine.UNDEFINED_VALUE) || beignValue.Equals(GuideLine.UNDEFINED_VALUE) || beignValue <= 0m || endValue <= 0m) return GuideLine.UNDEFINED_VALUE;
                
            beignValue = (beignValue == 0 || beignValue.Equals(GuideLine.UNDEFINED_VALUE) ? 1 : beignValue);
            
            return (decimal)Math.Round((Math.Pow((double)(endValue / beignValue), (double)(1d / (double)period)) - 1), 4);            
        }

        /// <summary>
        /// 根据期数、终值、复合增长率计算初值
        /// </summary>
        /// <param name="endValue">终值</param>
        /// <param name="cgr">复合增长率</param>
        /// <param name="period">期数</param>
        /// <returns></returns>
        public static decimal CalculateBeginValueByCGR(decimal endValue, decimal cgr, int period)
        {
            if (endValue == GuideLine.UNDEFINED_VALUE || cgr == GuideLine.UNDEFINED_VALUE || period <= 0 || endValue <= 0)
            { return GuideLine.UNDEFINED_VALUE; }

            return (decimal)Math.Round((double)endValue / (Math.Pow((double)(1 + cgr), (double)period)), 4);
        }

        /// <summary>
        /// 根据期数、初值、复合增长率计算终值
        /// </summary>
        /// <param name="beginValue">初值</param>
        /// <param name="cgr">复合增长率</param>
        /// <param name="period">期数</param>
        /// <returns></returns>
        public static decimal CalculateEndValueByCGR(decimal beginValue, decimal cgr, int period)
        {
            if (beginValue == GuideLine.UNDEFINED_VALUE || cgr == GuideLine.UNDEFINED_VALUE || period <= 0 || beginValue < 0)
            { return GuideLine.UNDEFINED_VALUE; }

            return (decimal)Math.Round((double)beginValue * (Math.Pow((double)(cgr + 1), (double)period)), 4);
        }

        /// <summary>
        /// 根据初值、复合增长率、终值计算期数
        /// </summary>
        /// <param name="beginValue"></param>
        /// <param name="cgr"></param>
        /// <param name="endValue"></param>
        /// <returns></returns>
        public static decimal CalculatePeriodByCGR(decimal beginValue, decimal cgr, decimal endValue)
        {
            if (beginValue == GuideLine.UNDEFINED_VALUE || beginValue <= 0 || cgr == GuideLine.UNDEFINED_VALUE || endValue == GuideLine.UNDEFINED_VALUE || endValue == 0)
            {
                return GuideLine.UNDEFINED_VALUE;
            }
            return (decimal)Math.Round(Math.Log((double)(endValue / beginValue), (double)(cgr + 1)), 4);
        }


        /// <summary>
        /// 获取复合增长率字符串
        /// </summary>
        /// <param name="beignValue">始值</param>
        /// <param name="endValue">终值</param>
        /// <param name="period">期数</param>
        /// <returns></returns>
        public static string GetCompoundGrowthRateString(decimal beignValue, decimal endValue, int period)
        {
            decimal v = CalculateCompoundGrowthRate(beignValue, endValue, period);

            return GetPercentString(v);
        }
    }
}
